#pragma once
#include "VC_Drawable.h"
//#define GUI_DEBUG
namespace gui {
	enum E_ContainerType {
		CONTAINER_VERTICAL = 0,
		CONTAINER_HORIZONTAL = 1
	};

	enum E_CoordType {
		COORD_TYPE_ABSOLUTE = 0,
		COORD_TYPE_RELATIVE = 1,
		COORD_TYPE_GRID		= 2
	};
	enum E_GridAlignVertical
	{
		GRID_TOP = 0,
		GRID_MIDDLE = 1,
		GRID_BOTTOM = 2
	};
	enum E_GridAlignHorizontal
	{
		GRID_LEFT = 0,
		GRID_CENTER = 1,
		GRID_RIGHT = 2
	};

	class C_Widget :
		public VC_Drawable
	{

	private:
		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	MAIN DATA
		sf::Vector2f	m_pos;	//relative position
		sf::Vector2f	m_aPos; //absolute position
		sf::Vector2f	m_size;
		glm::fvec4		m_backgroundColor;
		glm::fvec4		m_borderColor;

		glm::fvec4		m_margin; // r = left, g = right, b = top, a = bottom
		float			m_padding;

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	COORDINATE
		E_CoordType					m_coordType;
		E_ContainerType				m_containerType;
		E_GridAlignVertical			m_vAlign;
		E_GridAlignHorizontal		m_hAlign;

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	FAMILY
		C_Widget*					m_parent;
		std::vector<C_Widget*>		m_children;

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	INDEPENDENT  EVENT
		bool m_border;
		bool m_background;
		bool m_visible;
		bool m_focus;

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	DEPENDENT EVENTS
		bool				m_is_mouseOver;
		bool				m_is_mouseButtonPress;
		bool				m_is_mouseButtonClick;
		sf::Mouse::Button	m_mouseButton;

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	PARENT FUNCTION
		inline void setParent(C_Widget* parent) { m_parent = parent; }

		void updateX();
		void updateY();

	public:
		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	CONSTRUCTOR & DESTRUCTOR
		C_Widget(C_Widget* parent = NULL);
		virtual ~C_Widget();

		inline bool isMouseOver() { return m_is_mouseOver; }
		inline bool isMouseButtonPress() { return m_is_mouseButtonPress; }
		inline bool isMouseButtonClick() { return m_is_mouseButtonClick; }
		inline sf::Mouse::Button mouseButton() { return m_mouseButton; }

		void setVisible			 (bool v)	{ m_visible = v;		}
		void setBackgroundVisible(bool bv)	{ m_background = bv;	}
		void setBorderVisible	 (bool bv)	{ m_border = bv;		}

		bool getVisible()			{ return m_visible;		}
		bool getBackgroundVisible()	{ return m_background;	}
		bool getBorderVisible()		{ return m_border;		}

		void hide() { m_visible = false; if (m_parent != NULL) m_parent->complexUpdate(); }
		void show() { m_visible = true;  if (m_parent != NULL) m_parent->complexUpdate(); }
		void onFocus() { m_focus = true; }
		void offFocus() { m_focus = false; }


		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	EVENTS FUNCTIONS
		virtual void onClickButton(sf::Mouse::Button b_type);
		virtual void onPressButton(sf::Mouse::Button b_type);
		virtual void onReleaseButton(sf::Mouse::Button b_type);



		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	SET / GET COLOR BORDER
		inline void			setBorderColor(float r, float g, float b, float a = 1.0f)
		{
			m_borderColor.r = r;
			m_borderColor.g = g;
			m_borderColor.b = b;
			m_borderColor.a = a;
		}
		inline glm::fvec4 borderColor() { return m_borderColor; }



		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	SET / GET COLOR BACKGROUND
		inline void			setBackgroudColor(float r, float g, float b, float a = 1.0f)
		{
			m_backgroundColor.r = r;
			m_backgroundColor.g = g;
			m_backgroundColor.b = b;
			m_backgroundColor.a = a;
		}
		inline glm::fvec4 backgroundColor() { return m_backgroundColor; }



		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	SET / GET SIZE
		inline void			setSize(float w, float h) { m_size.x = w; m_size.y = h; }
		inline sf::Vector2f size() { return m_size; }



		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	SET / GET POSITION
		inline void			setPos(float x, float y) 
		{ 
			m_pos.x = x; m_pos.y = y; 
			m_aPos = (m_parent != NULL) ? m_parent->absolutePos() + m_pos : m_pos; 
			updateX(); updateY(); 
			//content
			syncWidgets();
		}
		inline sf::Vector2f pos	  (				   ) { return m_pos;			 }

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	SET / GET CONTAINER TYPE
		inline void				setContainerType(E_ContainerType ct) { m_containerType = ct; }
		inline E_ContainerType	containerType() { return m_containerType; }

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	SET / GET PADDING
		inline void			setPadding(float p) { m_padding = p; }
		inline float		padding()			{ return m_padding; }

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	SET / GET MARGIN
		inline void			setMargin(float left, float right, float top, float bottom)
		{
			m_margin.r = left;
			m_margin.g = right;
			m_margin.b = top;
			m_margin.a = bottom;
		}
		inline glm::fvec4	margin()		   { return m_margin; }

		inline sf::Vector2f absolutePos() { return m_aPos; }

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	ALIGN
		/// <summary>
		///	Set coordinate type
		/// </summary>
		void setCoordType(E_CoordType type);
		void setVerticalAlign(E_GridAlignVertical align);
		void setHorizontalAlign(E_GridAlignHorizontal align);


		C_Widget* addWidget(C_Widget* widget, E_CoordType type = COORD_TYPE_GRID);
		void complexUpdate() { updateX(); updateY(); }

		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	COUNTING FUNCTIONS
		float getWidgetsWidth();
		float getWidgetsHeight();
		float getMaxWidgetWidth();
		float getMaxWidgetHeight();
		float getMinWidgetWidth();
		float getMinWidgetHeight();


		/////////////////////////////////////////////////////////////////////////////////////////
		////////////////	MAIN FUNCTIONS
		virtual void renderWidget(); //for render contents
		virtual void syncWidgets(); //for synchronization with widgets position

		virtual void handleEvent(sf::Event e);
		virtual void render();
		virtual void update();
	};
}

